package cn.kn.triage.sys.service.impl;

import cn.kn.triage.common.config.jwt.JWTToken;
import cn.kn.triage.common.exception.CustomException;
import cn.kn.triage.common.model.*;
import cn.kn.triage.common.servic.BaseService;
import cn.kn.triage.common.utils.BeanCopy;
import cn.kn.triage.common.utils.JWTUtils;
import cn.kn.triage.common.utils.MD5Utils;
import cn.kn.triage.sys.dao.PermissionDao;
import cn.kn.triage.sys.dao.UserRoleDao;
import cn.kn.triage.sys.mapper.UserMapper;
import cn.kn.triage.sys.mapper.UserRoleMapper;
import cn.kn.triage.sys.model.User;
import cn.kn.triage.sys.model.UserExample;
import cn.kn.triage.sys.model.UserRole;
import cn.kn.triage.sys.model.UserRoleExample;
import cn.kn.triage.sys.service.UserService;
import cn.kn.triage.sys.vo.IUserVo;
import cn.kn.triage.sys.vo.MenuVo;
import cn.kn.triage.sys.vo.OUserVo;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author yinzn
 * @create 2020-10-18 17:29
 */
@Service
public class UserServiceImpl extends BaseService implements UserService {
    private final UserMapper userMapper;
    private final UserRoleMapper userRoleMapper;
    private final UserRoleDao userRoleDao;
    private final PermissionDao permissionDao;

    public UserServiceImpl(UserMapper userMapper, UserRoleMapper userRoleMapper, UserRoleDao userRoleDao, PermissionDao permissionDao) {
        this.userMapper = userMapper;
        this.userRoleMapper = userRoleMapper;
        this.userRoleDao = userRoleDao;
        this.permissionDao = permissionDao;
    }

    public void isExit(User user) {
        UserExample userExample = new UserExample();
        userExample.createCriteria().andIsstopEqualTo(false)
                .andCnameEqualTo(user.getCname());
        List<User> users = userMapper.selectByExample(userExample);
        if (!CollectionUtils.isEmpty(users)) {
            throw new CustomException(RCode.User_NAME_REPEAT);
        }
    }

    @Override
    public R add(User user) {
        isExit(user);
        int i = userMapper.insertSelective(user);
        return R.ok();
    }

    @Override
    public R del(Integer userId) {
        User user = new User();
        user.setId(userId);
        user.setIsstop(true);
        userMapper.updateByPrimaryKeySelective(user);
        return R.ok();
    }

    @Override
    public R get() {
        UserExample userExample = new UserExample();
        userExample.createCriteria().andIsstopEqualTo(false);
        List<User> users = userMapper.selectByExample(userExample);
        return R.ok(BeanCopy.beanCopy(users, OUserVo::new));
    }

    @Override
    public R list(PageBean pageBean, String userName) {
        UserExample userExample = new UserExample();
        UserExample.Criteria criteria = userExample.createCriteria()
                .andIsstopEqualTo(false);
        if (!StringUtils.isEmpty(userName)) {
            criteria.andCnameLike('%' + userName + '%');
        }
        PageHelper.startPage(pageBean.getCurPage(), pageBean.getPageSize());
        List<User> users = userMapper.selectByExample(userExample);
        PageInfo pageInfo = new PageInfo(users);
        return R.ok(new PageResult<>(pageInfo.getTotal(), BeanCopy.beanCopy(pageInfo.getList(), OUserVo::new)));
    }

    @Override
    public R update(Integer userId, IUserVo iUserVo) {
        User user = BeanCopy.beanCopy(iUserVo, User::new);
        user.setId(userId);
        userMapper.updateByPrimaryKeySelective(user);
        return R.ok();
    }

    @Override
    public R getRoleByUserId(Integer userId) {
        return R.ok(userRoleDao.getRoleByUserId(userId));
    }

    @Transactional
    @Override
    public R saveRoles(Integer userId, String roles, UserRole[] userRoles) {
        UserRoleExample userRoleExample = new UserRoleExample();
        userRoleExample.createCriteria().andUseridEqualTo(userId);
        userRoleMapper.deleteByExample(userRoleExample);
        User user = new User();
        user.setId(userId);
        if ("-1".equals(roles)) {
            roles = "-";
        } else {
            userRoleDao.batchInsert(userRoles);
        }
        user.setRoles(roles);
        userMapper.updateByPrimaryKeySelective(user);

        return R.ok();
    }

    @Override
    public R getMenu() {
        List<MenuVo> menus = permissionDao.getMenu(getUserId());
        List<MenuVo> res = new ArrayList<>();
        //createMenu(menus,res, Constant.PID);/*java 7  做法*/
        return R.ok(createMenu(menus,Constant.PID));/*java 8  做法*/
    }

    @Override
    public R login(String username, String password) {
        String token;
        UserExample example =new UserExample();
        example.createCriteria().andLnameEqualTo(username);
        List<User> users = userMapper.selectByExample(example);

        if (!CollectionUtils.isEmpty(users)) {
            User user = users.get(0);
            String salt = user.getLname();
            //秘钥为盐
            String target = MD5Utils.md5Encryption(password, salt);
            //生成Token
            token = JWTUtils.sign(username, target);
            JWTToken jwtToken = new JWTToken(token);
            try {
                SecurityUtils.getSubject().login(jwtToken);
            } catch (AuthenticationException e) {
                throw new CustomException(RCode.NO_USER);
            }
        } else {
            throw new CustomException(RCode.NO_USER);
        }
        Map<String,Object> map =new HashMap<>();
        map.put("token",token);
        map.put("perms",getActiverUser().getPerms());
        return R.ok(map);
    }

    /*java7 */
    private void createMenu(List<MenuVo> menus, List<MenuVo> res, Integer pid) {
        for (MenuVo m : menus) {
            if (m.getPid().equals(pid)) {
                ArrayList<MenuVo> temp = new ArrayList<>();
                createMenu(menus,temp,m.getId());
                if (temp.size()>0){
                    m.setChildren(temp);
                }
                res.add(m);
            }
        }

    }

    /*java8  */
    private List<MenuVo> createMenu(List<MenuVo> menus, Integer pid) {
        return menus.stream()
                .filter(n->n.getPid().equals(pid))/*符合的数据过滤出来  过滤第一层*/
                /*把过滤出来的元素包装起来*/
                .map(m->{
                    List<MenuVo> menu = createMenu(menus, m.getId() );
                    if (menu.size()>0){
                        m.setChildren(menu);
                    }
                    return m;
                }).collect(Collectors.toList());/*把map包装成list集合*/

    }

}
